
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            .markdown-body {
                box-sizing: border-box;
                min-width: 200px;
                max-width: 1000px;
                margin: 0 auto;
                padding: 45px;
            }
            @media (max-width: 750px) {
                .markdown-body {
                    padding: 15px;
                }
            }
            :root {
  --side-bar-bg-color: #fafafa;
  --control-text-color: #777;
}

@include-when-export url(https://fonts.loli.net/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext);

@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: normal;
  src: local('Open Sans Regular'),url('./github/400.woff') format('woff');
}

@font-face {
  font-family: 'Open Sans';
  font-style: italic;
  font-weight: normal;
  src: local('Open Sans Italic'),url('./github/400i.woff') format('woff');
}

@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: bold;
  src: local('Open Sans Bold'),url('./github/700.woff') format('woff');
}

@font-face {
  font-family: 'Open Sans';
  font-style: italic;
  font-weight: bold;
  src: local('Open Sans Bold Italic'),url('./github/700i.woff') format('woff');
}

html {
  font-size: 16px;
}

body {
  font-family: "Open Sans","Clear Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
  color: rgb(51, 51, 51);
  line-height: 1.6;
}

#write {
  max-width: 860px;
  margin: 0 auto;
  padding: 30px;
  padding-bottom: 100px;
}
#write > ul:first-child,
#write > ol:first-child{
  margin-top: 30px;
}

a {
  color: #4183C4;
}
h1,
h2,
h3,
h4,
h5,
h6 {
  position: relative;
  margin-top: 1rem;
  margin-bottom: 1rem;
  font-weight: bold;
  line-height: 1.4;
  cursor: text;
}
h1:hover a.anchor,
h2:hover a.anchor,
h3:hover a.anchor,
h4:hover a.anchor,
h5:hover a.anchor,
h6:hover a.anchor {
  text-decoration: none;
}
h1 tt,
h1 code {
  font-size: inherit;
}
h2 tt,
h2 code {
  font-size: inherit;
}
h3 tt,
h3 code {
  font-size: inherit;
}
h4 tt,
h4 code {
  font-size: inherit;
}
h5 tt,
h5 code {
  font-size: inherit;
}
h6 tt,
h6 code {
  font-size: inherit;
}
h1 {
  padding-bottom: .3em;
  font-size: 2.25em;
  line-height: 1.2;
  border-bottom: 1px solid #eee;
}
h2 {
 padding-bottom: .3em;
  font-size: 1.75em;
  line-height: 1.225;
  border-bottom: 1px solid #eee;
}
h3 {
  font-size: 1.5em;
  line-height: 1.43;
}
h4 {
  font-size: 1.25em;
}
h5 {
  font-size: 1em;
}
h6 {
 font-size: 1em;
  color: #777;
}
p,
blockquote,
ul,
ol,
dl,
table{
  margin: 0.8em 0;
}
li>ol,
li>ul {
  margin: 0 0;
}
hr {
  height: 2px;
  padding: 0;
  margin: 16px 0;
  background-color: #e7e7e7;
  border: 0 none;
  overflow: hidden;
  box-sizing: content-box;
}

li p.first {
  display: inline-block;
}
ul,
ol {
  padding-left: 30px;
}
ul:first-child,
ol:first-child {
  margin-top: 0;
}
ul:last-child,
ol:last-child {
  margin-bottom: 0;
}
blockquote {
  border-left: 4px solid #dfe2e5;
  padding: 0 15px;
  color: #777777;
}
blockquote blockquote {
  padding-right: 0;
}
table {
  padding: 0;
  word-break: initial;
}
table tr {
  border-top: 1px solid #dfe2e5;
  margin: 0;
  padding: 0;
}
table tr:nth-child(2n),
thead {
  background-color: #f8f8f8;
}
table tr th {
  font-weight: bold;
  border: 1px solid #dfe2e5;
  border-bottom: 0;
  margin: 0;
  padding: 6px 13px;
}
table tr td {
  border: 1px solid #dfe2e5;
  margin: 0;
  padding: 6px 13px;
}
table tr th:first-child,
table tr td:first-child {
  margin-top: 0;
}
table tr th:last-child,
table tr td:last-child {
  margin-bottom: 0;
}

.CodeMirror-lines {
  padding-left: 4px;
}

.code-tooltip {
  box-shadow: 0 1px 1px 0 rgba(0,28,36,.3);
  border-top: 1px solid #eef2f2;
}

.md-fences,
code,
tt {
  border: 1px solid #e7eaed;
  background-color: #f8f8f8;
  border-radius: 3px;
  padding: 0;
  padding: 2px 4px 0px 4px;
  font-size: 0.9em;
}

code {
  background-color: #f3f4f4;
  padding: 0 2px 0 2px;
}

.md-fences {
  margin-bottom: 15px;
  margin-top: 15px;
  padding-top: 8px;
  padding-bottom: 6px;
}


.md-task-list-item > input {
margin-left: -1.3em;
}

@media print {
  html {
      font-size: 13px;
  }
  table,
  pre {
      page-break-inside: avoid;
  }
  pre {
      word-wrap: break-word;
  }
}

.md-fences {
background-color: #f8f8f8;
}
#write pre.md-meta-block {
padding: 1rem;
  font-size: 85%;
  line-height: 1.45;
  background-color: #f7f7f7;
  border: 0;
  border-radius: 3px;
  color: #777777;
  margin-top: 0 !important;
}

.mathjax-block>.code-tooltip {
bottom: .375rem;
}

.md-mathjax-midline {
  background: #fafafa;
}

#write>h3.md-focus:before{
left: -1.5625rem;
top: .375rem;
}
#write>h4.md-focus:before{
left: -1.5625rem;
top: .285714286rem;
}
#write>h5.md-focus:before{
left: -1.5625rem;
top: .285714286rem;
}
#write>h6.md-focus:before{
left: -1.5625rem;
top: .285714286rem;
}
.md-image>.md-meta {
  /*border: 1px solid #ddd;*/
  border-radius: 3px;
  padding: 2px 0px 0px 4px;
  font-size: 0.9em;
  color: inherit;
}

.md-tag {
  color: #a7a7a7;
  opacity: 1;
}

.md-toc { 
  margin-top:20px;
  padding-bottom:20px;
}

.sidebar-tabs {
  border-bottom: none;
}

#typora-quick-open {
  border: 1px solid #ddd;
  background-color: #f8f8f8;
}

#typora-quick-open-item {
  background-color: #FAFAFA;
  border-color: #FEFEFE #e5e5e5 #e5e5e5 #eee;
  border-style: solid;
  border-width: 1px;
}

/** focus mode */
.on-focus-mode blockquote {
  border-left-color: rgba(85, 85, 85, 0.12);
}

header, .context-menu, .megamenu-content, footer{
  font-family: "Segoe UI", "Arial", sans-serif;
}

.file-node-content:hover .file-node-icon,
.file-node-content:hover .file-node-open-state{
  visibility: visible;
}

.mac-seamless-mode #typora-sidebar {
  background-color: #fafafa;
  background-color: var(--side-bar-bg-color);
}

.md-lang {
  color: #b4654d;
}

.html-for-mac .context-menu {
  --item-hover-bg-color: #E6F0FE;
}

#md-notification .btn {
  border: 0;
}

.dropdown-menu .divider {
  border-color: #e5e5e5;
}

.ty-preferences .window-content {
  background-color: #fafafa;
}

.ty-preferences .nav-group-item.active {
  color: white;
  background: #999;
}
        </style>
    </head>
    <body>
        <div class="markdown-body">
            <h1 id="nodejs">Nodejs</h1>
<h2 id="nodejs-可以做什么">Nodejs 可以做什么</h2>
<ul>
<li>轻量级、高性能的 Web 服务</li>
<li>前后端 JavaScript 同构开发</li>
<li>便捷高效的前端工程化</li>
</ul>
<h2 id="nodejs-的架构和运行过程">Nodejs 的架构和运行过程</h2>
<p><img src="assets/1.png" alt="image-20210312-0.png"></p>
<h3 id="native-modules">Native modules</h3>
<ul>
<li>当前层内容由js 实现</li>
<li>提供应用程序可直接调用库，例如 fs path http 等</li>
<li>js 语言无法直接操作底层硬件设置</li>
</ul>
<h3 id="builtin-modules-胶水层">builtin modules &quot;胶水层&quot;</h3>
<p><img src="assets/2.png" alt="image-20210312-0.png"></p>
<h3 id="底层">底层</h3>
<ul>
<li>v8： 执行js代码，提供桥梁接口</li>
<li>libuv： 事件循环、事件队列、异步IO</li>
<li>第三方模块： zlib、 http、 c-ares 等</li>
</ul>
<h3 id="为什么是-nodejs？">为什么是 Nodejs？</h3>
<p><img src="assets/3.png" alt="image-20210312-0.png"></p>
<p>IO 是计算机操作过程中最缓慢的环节</p>
<p><img src="assets/4.png" alt="image-20210312-0.png"></p>
<p>Reactor 模式，单线程完成多线程工作
Reactor 模式下实现异步 IO、事件驱动
Nodejs 更适用于 IO 密集型高并发请求</p>
<h2 id="nodejs-异步io和事件驱动">Nodejs 异步IO和事件驱动</h2>
<p>非阻塞IO / 阻塞IO</p>
<p>重复调用IO操作，判断IO操作是否结束</p>
<p>轮询</p>
<p>read、 select、poll、enqueue、 event ports</p>
<p>libuv 库看成是几种不同的异步IO实现方式的抽象封装层</p>
<p>在运行了一段 nodejs 代码之后，最终会走到libuv 库这个环节里面，它就可以对当前平台进行判断，然后再依据平台调用相应的异步IO处理方法</p>
<p><img src="assets/5.png" alt="image-20210312-0.png"></p>
<p><img src="assets/6.png" alt="image-20210312-0.png"></p>
<p>期望实现无须主动判断的非阻塞IO</p>
<p>异步IO总结</p>
<ul>
<li>IO 是应用程序的瓶颈所在，肯定要消耗时间的，跟物理设备有关系</li>
<li>异步 IO 提高性能无需原地等待结果返回</li>
<li>IO 操作属于操作系统级别，平台都有对应实现，libuv 库对不同的操作平台进行封装</li>
<li>Nodejs 单线程配合事件驱动架构及libuv 实现异步IO</li>
</ul>
<p>事件驱动的体现在于
有人发布了事件，然后呢订阅这个事件的人在将来呢，去接受到具体的事件消息发布之后呢，就会执行订阅时所注册的处理程序
处理由异步非阻塞操作带来的数据获取问题</p>
<pre><code class="language-javascript">const EventEmitter = require(&#39;events&#39;)

const myEvent = new EventEmitter()

// 事件订阅
myEvent.on(&#39;事件1&#39;, () =&gt; {
  console.log(&#39;事件1 执行了&#39;)
})

myEvent.on(&#39;事件1&#39;, () =&gt; {
  console.log(&#39;事件1-2 执行了&#39;)
})

// 事件触发 发布者
myEvent.emit(&#39;事件1&#39;)
</code></pre>
<p>一件事触发之后，可以有多个订阅事件</p>
<h2 id="nodejs-单线程">Nodejs 单线程</h2>
<p>使用js 实现高效可伸缩的高性能 Web 服务</p>
<p>单线程如何实现高并发 ？</p>
<p>异步非阻塞 IO 配合事件回调通知</p>
<p>Nodejs 主线程是单线程</p>
<p><img src="assets/5.png" alt="image-20210312-0.png"></p>
<pre><code class="language-javascript">const http = require(&#39;http&#39;)

const server = http.createServer((req, res) =&gt; {
  res.end(&#39;server start.....&#39;)
})

function sleepTime(time) {
  const sleep = Date.now() + time * 1000
  while (Date.now() &lt; sleep) {}
  return
}

sleepTime(4)
server.listen(8080, () =&gt; {
  console.log(&#39;服务启动了&#39;)
})
</code></pre>
<h2 id="nodejs-应用场景">Nodejs 应用场景</h2>
<p>更加适合IO 密集型高并发请求
例如：</p>
<ol>
<li>操作数据库提供API服务</li>
<li>实时聊天应用程序</li>
</ol>
<p>不合适业务逻辑复杂的场景
<img src="assets/7.png" alt="image-20210312-0.png"></p>
<h2 id="nodejs-实现api-服务">Nodejs 实现Api 服务</h2>
<h2 id="nodejs-核心模块-及-api-使用">Nodejs 核心模块 及 APi 使用</h2>
<h3 id="nodejs-全局对象">Nodejs 全局对象</h3>
<ul>
<li>与浏览器平台的window 不完全相同</li>
<li>全局对象是 javascript 中特殊对象</li>
<li>Nodejs 中全局对象是global</li>
<li>global 的根本作用就是作为宿主</li>
<li>全局对象可以看做是全局变量的宿主</li>
</ul>
<h3 id="nodejs-常见全局变量">Nodejs 常见全局变量</h3>
<ul>
<li>__filename: 返回正在执行脚本文件的绝对路径</li>
<li>__dirname: 返回正在执行脚本所在目录</li>
<li>timer 类函数： 执行顺序与事件循环间的关系</li>
<li>process: 提供与当前进程互动的接口</li>
<li>require： 实现模块的加载</li>
<li>module export： 处理模块的导出</li>
</ul>
<h3 id="全局变量-process">全局变量 process</h3>
<p>获取进程信息</p>
<ul>
<li>资源： cpu 内存</li>
<li>运行环境： 运行目录 node环境 cup 架构 用户环境 系统平台</li>
<li>运行状态：启动参数 PID 运行时间</li>
</ul>
<pre><code class="language-javascript">console.log(process.cwd())
// 退出事件

process.on(&#39;exit&#39;, (code) =&gt; {
  console.log(&#39;exit&#39;, code)
})
process.on(&#39;beforeExit&#39;, code =&gt; {
  console.log(&#39;beforeExit&#39;, code)
})

process.exit() // 主动退出程序
console.log(&#39;代码执行完了&#39;)
</code></pre>
<p>beforeExit 可以执行异步代码
exit 只能执行同步代码</p>
<p>发布/订阅 监听事件模式</p>
<p>标准输入 输出 错误 管道操作</p>
<pre><code class="language-javascript">console.log = function(data) {
  process.stdout.write(&#39;-----&#39; + data + &#39;\n&#39;)
}

console.log(11)
console.log(22)

process.stdin.setEncoding(&#39;utf-8&#39;)
process.stdin.on(&#39;readable&#39;, () =&gt; {
  let chunk = process.stdin.read()
  if (chunk != null) {
    process.stdout.write(&#39;data &#39; + chunk)
  }
})
</code></pre>
<p>stdout 标准输出
sudin 标准输入</p>
<h3 id="核心模块---path">核心模块 - path</h3>
<ul>
<li>basename() 获取路径中基础名称</li>
<li>dirname() 获取路径中目录名称</li>
<li>extname() 获取路径中扩展名称</li>
<li>isAbsolute() 获取路径是否为绝对路径</li>
<li>join() 拼接多个路径片段</li>
<li>resolve() 返回绝对路径</li>
<li>parse() 解析路径</li>
<li>format() 序列化路径</li>
<li>normalize() 规范化路径</li>
</ul>
<h3 id="buffer">Buffer</h3>
<p>Buffer 让 JavaScript 可以操作二进制</p>
<p>JavaScript 语言起初服务于浏览器平台</p>
<p>Nodejs 平台下 JavaScript 可实现 IO</p>
<p>IO 行为操作的就是二进制数据</p>
<p>Stream 流操作并非 Nodejs 独创</p>
<p>流操作配合管道实现数据分段传输 （直播）</p>
<p>数据的端到端传输会有生产者和消费者 （速度不一样） 等待/不够消费的数据 存放在缓存区</p>
<p>Nodejs 中 Buffer 是一片内存空间</p>
<ul>
<li>无须 require 的一个全局变量</li>
<li>实现 Nodejs 平台下的二进制数据操作</li>
<li>不占据 V8 堆内存大小的内存控件</li>
<li>内存的使用由 Node 来控制，由 V8 的 GC 回收</li>
<li>一般配合 Stream 流使用，充当数据缓存区</li>
</ul>
<p><img src="assets/8.png" alt="image-20210312-0.png"></p>
<h4 id="创建-buffer-实例">创建 Buffer 实例</h4>
<ul>
<li>alloc：创建指定字节大小的 Buffer</li>
<li>allocUnsafe： 创建指定大小的 Buffer （不安全）</li>
<li>from: 接收数据，创建 Buffer</li>
</ul>
<h4 id="buffer-实例方法">Buffer 实例方法</h4>
<ul>
<li>fill 使用数据填充 buffer</li>
<li>write 向buffer写入数据</li>
<li>toString 从buffer提取数据</li>
<li>slice 截取 buffer</li>
<li>indexOf 在buffer中查找数据</li>
<li>copy 拷贝 buffer中的数据<pre><code class="language-javascript">// fill
</code></pre>
</li>
</ul>
<p>let buf = Buffer.alloc(6)</p>
<p>buf.fill(&#39;123&#39;, 1, 3) // 从第一个位置写入，顾头不顾尾
console.log(buf) // 00 00 00 00 00 00
console.log(buf.toString()) // 12</p>
<pre><code>
#### Buffer 静态方法
- concat 
- isBuffer 

#### 自定义Buffer 之 split
```javascript
ArrayBuffer.prototype.split = function(sep) {
  let len = Buffer.from(sep).length
  let ret = []
  let start = 0
  let offset = 0
  while (offset = this.indexOf(sep, start) !== -1) {
    ret.push(this.slice(start, offset))
    start = offset + len
  }
  ret.push(this.slice(start))
  return ret
}
</code></pre>
<h2 id="核心模块之-fs">核心模块之 FS</h2>
<p>Buffer 、Stream 与 FS 有什么关系</p>
<p>FS 是内置核心模块，提供文件系统操作的API</p>
<p><img src="assets/9.png" alt="image-20210312-0.png"></p>
<p>FS 模块结构</p>
<p>FS基本操作类
权限位
常见 flag 操作符 标识符</p>
<ul>
<li>r 表示可读</li>
<li>w 表示可写</li>
<li>s 表示同步</li>
<li><ul>
<li>表示执行相反操作</li>
</ul>
</li>
<li>x 表示排它操作</li>
<li>a 表示追加操作</li>
</ul>
<p>fd 就是操作系统分配给被打开文件的标识</p>
<p>fs 介绍总结</p>
<ul>
<li>fs 是 Nodejs 中内置核心模块</li>
<li>代码层面上fs分为基本操作类和常用API</li>
<li>权限位、标识符、操作符</li>
</ul>
<h3 id="文件操作api-文件读写与拷贝操作">文件操作API 文件读写与拷贝操作</h3>
<p>同步操作
异步操作： </p>
<ul>
<li>readFile: 从指定文件中读取数据</li>
<li>writeFil： 向指定文件中写入数据</li>
<li>appendFile： 追加的方式向指定文件中写入数据</li>
<li>copyFile：将某个文件中的数据拷贝至另一个文件</li>
<li>watchFile： 对指定文件进行监控</li>
</ul>
<h3 id="文件操作实现-md-转-html">文件操作实现 md 转 html</h3>

        </div>
    </body>
    </html>
